package com.atguigu.gulimall.auth.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.atguigu.common.constant.AuthServerConstant;
import com.atguigu.common.exception.BizExceptionEnum;
import com.atguigu.common.utils.R;
import com.atguigu.common.utils.RandomUtils;
import com.atguigu.gulimall.auth.feign.MemberFeignService;
import com.atguigu.gulimall.auth.feign.SmsFeignService;
import com.atguigu.gulimall.auth.service.LoginService;
import com.atguigu.gulimall.auth.vo.LoginVo;
import com.atguigu.common.vo.MemberRespVo;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

/**
 * @DESCRIPTION:
 * @author: zr
 * @DATE: 2022/12/31 11:38
 */
@Service
@Slf4j
public class LoginServiceImpl implements LoginService {
    @Autowired
    private SmsFeignService smsFeignService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private MemberFeignService memberFeignService;

    /**
     * 发送短信验证码 使用redis 防止接口防刷
     *
     * @param phone
     * @return
     */
    @Override
    public R sendCode(String phone) {
        // TODO 接口防刷
        // 处理一个手机号码60s内多次获取短信验证码问题
        String phoneCache = stringRedisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone);
        if (StringUtils.isNotEmpty(phoneCache)) {
            // 获取存储的系统时间
            Long saveTime = Long.parseLong(phoneCache.split("_")[1]);
            // 单位为ms 所有要将60s转为ms
            if ((saveTime - System.currentTimeMillis()) < 60000) {
                return R.error(BizExceptionEnum.SMS_CODE_EXCEPTION.getCode(), BizExceptionEnum.SMS_CODE_EXCEPTION.getMsg());
            }
        }
        // 生成6位随机数
        String code = RandomUtils.getSixBitRandom();
        // redis中存10min
        stringRedisTemplate.opsForValue().set(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone, code + "_" + System.currentTimeMillis(), 10, TimeUnit.MINUTES);
        smsFeignService.sendCode(phone, code);
        return R.ok();
    }

    @Override
    public String login(LoginVo loginVo, HttpSession session, RedirectAttributes redirectAttributes) {
        R login = memberFeignService.login(loginVo);
        if (login.getCode() == 0) {
            MemberRespVo memberRespVo = login.getData("data", new TypeReference<MemberRespVo>() {
            });
            log.info("登录成功：用户:{}", memberRespVo.toString());
            // TODO 1、默认发的令牌 session=dagjldjf  作用域: 当前域; (解决子域共享问题)
            // TODO 2、使用JSON的序列化方式来序列化对象数据到redis中
            session.setAttribute(AuthServerConstant.LOGIN_USER, memberRespVo);
            // 登录成功
            return "redirect:http://gulimall.com";
        } else {
            HashMap<Object, Object> map = Maps.newHashMap();
            map.put("msg", login.getData("msg", new TypeReference<String>() {
            }));
            redirectAttributes.addFlashAttribute("errors", map);
            return "redirect:http://auth.gulimall.com/login.html";
        }
    }
}
